package com.lsz.flight_system.service.Impl;

import com.lsz.flight_system.entity.BuyTicketsMessage;
import com.lsz.flight_system.entity.PlaneMessage;
import com.lsz.flight_system.entity.UserMessage;
import com.lsz.flight_system.repository.PlaneMessageRepository;
import com.lsz.flight_system.repository.UserMessageRepository;
import com.lsz.flight_system.service.BuyTicketsMessageService;
import com.lsz.flight_system.service.PlaneMessageService;
import com.lsz.flight_system.service.UserMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class PlaneMessageServiceImpl implements PlaneMessageService {

    @Autowired
    PlaneMessageRepository planeMessageRepository;

    @Autowired
    BuyTicketsMessageService buyTicketsMessageService;

    @Autowired
    UserMessageService userMessageService;

    @Autowired
    UserMessageRepository userMessageRepository;

    @Override
    public List<PlaneMessage> findAllPlaceMessage(Map<String, Object> map) {

        List<PlaneMessage> planeList = planeMessageRepository.findAll();
        //如果时间过了，将状态改为停售
        for (PlaneMessage plane : planeList){
            if (plane.getStartTime().isBefore(LocalDateTime.now())){
                plane.setPlaneState("停售");
                planeMessageRepository.save(plane);
            }
        }
        return planeMessageRepository.findAll(new Specification<PlaneMessage>() {
            @Override
            public Predicate toPredicate(Root<PlaneMessage> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<>();
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

                if (map.containsKey("planeId") && !StringUtils.isEmpty(map.get("planeId"))){
                    predicateList
                            .add(cb.equal(root.get("planeId").as(String.class),map.get("planeId")));
                }
                if (map.containsKey("origin") && !StringUtils.isEmpty(map.get("origin"))){
                    predicateList
                            .add(cb.like(root.get("origin"),"%"+map.get("origin").toString()+"%"));
                }
                if (map.containsKey("destination") && !StringUtils.isEmpty(map.get("destination"))){
                    predicateList
                            .add(cb.like(root.get("destination"),"%"+map.get("destination").toString()+"%"));
                }
                // 出发时间
                if (map.containsKey("startTime") && !StringUtils.isEmpty(map.get("startTime"))) {
                    LocalDateTime localStartTime = LocalDateTime.parse(map.get("startTime").toString()+" 00:00:00", fmt);
                    LocalDateTime localEndTime = LocalDateTime.parse(map.get("startTime").toString()+ " 23:59:59", fmt);
//                    Predicate predicate1 = cb.greaterThanOrEqualTo(root.get("startTime").as(LocalDateTime.class),
//                            localStartTime);
//                    Predicate predicate2 = cb.lessThanOrEqualTo(root.get("startTime").as(LocalDateTime.class),
//                            localEndTime);
//                    predicateList.add(predicate1);
//                    predicateList.add(predicate2);
                    Predicate predicate = cb.between(root.get("startTime").as(LocalDateTime.class),localStartTime,localEndTime);
                    predicateList.add(predicate);
                }

                Predicate[] predicateArr = new Predicate[predicateList.size()];
                return cb.and(predicateList.toArray(predicateArr));
            }
        });
    }

    @Override
    public PlaneMessage findByPlaneId(String planeId) {
        return planeMessageRepository.findPlaneMessageByPlaneId(planeId);
    }

    @Override
    public boolean updateRemainTicket(String planeId) {
        PlaneMessage planeMessage = planeMessageRepository.findPlaneMessageByPlaneId(planeId);
        int remainTicket = planeMessage.getRemainTicket();
        if (!Objects.equals(planeMessage.getPlaneState(), "售票")){
            return false;
        }
        if (remainTicket == 0) {
            return false;
        } else if ((remainTicket - 1) == 0){
            planeMessage.setPlaneState("无票");
        }
            planeMessage.setRemainTicket(remainTicket - 1);
        if (planeMessage.getRemainTicket() == (remainTicket - 1)) {
            planeMessageRepository.save(planeMessage);
            return true;
        }
        return false;
    }

    //用户换票，Controller层还未实现，未判断航班是否有票
    @Override
    public BuyTicketsMessage userChangeTickets(Long id, String planeId) {
        BuyTicketsMessage buyTicketsMessage = buyTicketsMessageService.findBuyTicketsMessageById(id);
        //获取之前票的信息
        PlaneMessage ticketMessage = planeMessageRepository.findPlaneMessageByPlaneId(buyTicketsMessage.getPlaneId());
        //获取要换票的信息
        PlaneMessage planeMessage = planeMessageRepository.findPlaneMessageByPlaneId(planeId);
        UserMessage userMessage = userMessageService.getUserMessageByUsername(buyTicketsMessage.getUsername());
        int remainTicket = planeMessage.getRemainTicket() - 1;
        planeMessage.setRemainTicket(remainTicket);
        if (remainTicket == 0){
            planeMessage.setPlaneState("无票");
        }
        ticketMessage.setRemainTicket(ticketMessage.getRemainTicket()+1);
        planeMessageRepository.save(ticketMessage);
        planeMessageRepository.save(planeMessage);
        buyTicketsMessage.setPlaneId(planeMessage.getPlaneId());
        buyTicketsMessage.setTicketState("换购");
        buyTicketsMessage.setPlaneRoute(planeMessage.getPlaneRoute());
        buyTicketsMessage.setBuyTime(LocalDateTime.now());
        buyTicketsMessageService.addBuyTicketsMessage(buyTicketsMessage);
        //更新用户余额，多退少补
        userMessage.setBalance(userMessage.getBalance() + ticketMessage.getTicketPrice() - planeMessage.getTicketPrice());
        userMessageRepository.save(userMessage);
        return buyTicketsMessage;
    }

    @Override
    public boolean delPlaneMessageById(String planeId) {
        planeMessageRepository.delete(planeMessageRepository.findPlaneMessageByPlaneId(planeId));
//        planeMessageRepository.deleteByPlaneId(planeId);//使用该方法会抛异常
        if (planeMessageRepository.findPlaneMessageByPlaneId(planeId)==null){
            return true;
        }
        return false;
    }

    @Override
    public boolean editPlaneMessage(PlaneMessage planeMessage) {
        try {
            planeMessageRepository.save(planeMessage);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public PlaneMessage getPlaneMessage(String planeId, String origin, String destination, String startTime, String arriveTime, int seats, int remainTicket, float ticketPrice, String planeState,String planeRoute) {
        PlaneMessage planeMessage = new PlaneMessage();
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        if (startTime.length()<18){startTime=startTime+":00";}
        if (arriveTime.length()<18){arriveTime=arriveTime+":00";}
        LocalDateTime start = LocalDateTime.parse(startTime,fmt);
        LocalDateTime arrive = LocalDateTime.parse(arriveTime,fmt);
        planeMessage.setPlaneId(planeId);
        planeMessage.setOrigin(origin);
        planeMessage.setDestination(destination);
        planeMessage.setStartTime(start);
        planeMessage.setArriveTime(arrive);
        planeMessage.setSeats(seats);
        planeMessage.setRemainTicket(remainTicket);
        planeMessage.setTicketPrice(ticketPrice);
        planeMessage.setPlaneState(planeState);
        planeMessage.setPlaneRoute(planeRoute);
        return planeMessage;
    }
}
